1 module modular_db.database;
2 
3 public import d2sqlite3;
4 
5 @system:
6 
7 struct Transaction {
8     private {
9         d2sqlite3.Database _db;
10         bool _nested;
11     }
12 
13     package this(d2sqlite3.Database db, bool nested) {
14         db.execute(nested ? "SAVEPOINT _modular_db_save" : "BEGIN");
15         _db = db;
16         _nested = nested;
17     }
18 
19     @disable this(this);
20 
21     ~this() {
22         if (_db !is d2sqlite3.Database.init)
23             _db.execute(_nested ? "ROLLBACK TO _modular_db_save" : "ROLLBACK");
24     }
25 
26     @property bool nested() const nothrow pure @safe @nogc {
27         return _nested;
28     }
29 
30     void commit()
31     in {
32         assert(_db !is d2sqlite3.Database.init, "Attempting to commit a closed transaction");
33     }
34     do {
35         _db.execute(_nested ? "RELEASE _modular_db_save" : "COMMIT");
36         _db = d2sqlite3.Database.init;
37     }
38 }
39 
40 // N.B.: Make it ref-counted if adding extra fields.
41 struct Database {
42     d2sqlite3.Database raw;
43 
44     alias raw this;
45 
46     @property bool inTransaction() nothrow
47     in {
48         assert(raw.handle !is null, "Attempting to query transaction status in a closed database");
49     }
50     do {
51         import d2sqlite3.sqlite3;
52 
53         return !sqlite3_get_autocommit(raw.handle);
54     }
55 
56     Transaction startTransaction()
57     in {
58         assert(raw.handle !is null, "Attempting to start a transaction in a closed database");
59     }
60     do {
61         return Transaction(raw, inTransaction);
62     }
63 }